import os
import yaml
from flask import Flask, render_template, request, jsonify
import sys
from datetime import datetime

# Add the project root to the Python path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from generate_image import generate_image, load_config

app = Flask(__name__)
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
CONFIGS_DIR = os.path.join(PROJECT_ROOT, 'configs')
STATIC_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static')
GENERATED_DIR = os.path.join(STATIC_DIR, 'generated_images')

os.makedirs(GENERATED_DIR, exist_ok=True)

def get_config_files():
    """Scan the configs directory and return a list of .yml files."""
    return [f for f in os.listdir(CONFIGS_DIR) if f.endswith(('.yml', '.yaml'))]

def make_font_paths_absolute(config, base_path):
    """Adjusts font paths in the config to be absolute."""
    if 'fonts' in config:
        for key, font_path in config['fonts'].items():
            if not os.path.isabs(font_path):
                config['fonts'][key] = os.path.join(base_path, font_path)
    return config

@app.route('/')
def index():
    """Render the main page and pre-generate a default image."""
    config_files = get_config_files()
    default_config_name = 'configphone.yml'
    if default_config_name not in config_files:
        default_config_name = config_files[0] if config_files else None
    
    config = {}
    initial_image_url = None
    if default_config_name:
        config = load_config(os.path.join(CONFIGS_DIR, default_config_name))
        
        # Pre-generate image
        try:
            gen_config = config.copy()
            make_font_paths_absolute(gen_config, PROJECT_ROOT)
            
            title_text = gen_config.get('title', {}).get('texts_to_generate', ['默认标题'])[0]
            
            image = generate_image(gen_config, title_text)
            
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"initial_{timestamp}.png"
            output_path = os.path.join(GENERATED_DIR, filename)
            image.save(output_path)
            
            initial_image_url = f'/static/generated_images/{filename}'
        except Exception as e:
            print(f"Error during initial image generation: {e}")

    return render_template('index.html', 
                           config_files=config_files, 
                           config=config, 
                           selected_config=default_config_name, 
                           initial_image_url=initial_image_url)

@app.route('/load_config/<filename>')
def get_config_data(filename):
    """Load a specific YAML config file and return it as JSON."""
    if filename in get_config_files():
        config_path = os.path.join(CONFIGS_DIR, filename)
        config = load_config(config_path)
        return jsonify(config)
    return jsonify({'error': 'File not found'}), 404

def deep_update(source, overrides):
    """
    Update a nested dictionary or similar mapping.
    Modifies source in place.
    """
    for key, value in overrides.items():
        if isinstance(value, dict) and key in source and isinstance(source.get(key), dict):
            source[key] = deep_update(source.get(key, {}), value)
        else:
            source[key] = value
    return source

@app.route('/generate', methods=['POST'])
def generate():
    """Generate an image based on form data."""
    # Use to_dict(flat=False) to get all values for each key
    form_data_multidict = request.form.to_dict(flat=False)
    
    # Process the multidict to get the last value for each key
    form_data = {key: values[-1] for key, values in form_data_multidict.items()}
    
    selected_config_file = form_data.get('selected_config')
    if not selected_config_file:
        return jsonify({'error': 'No config file selected'}), 400
    config_path = os.path.join(CONFIGS_DIR, selected_config_file)
    config = load_config(config_path)

    form_config = {}
    for key, value in form_data.items():
        if key in ['selected_config', 'main_title_text']:
            continue
        
        parts = key.split('.')
        d = form_config
        for part in parts[:-1]:
            d = d.setdefault(part, {})

        final_value = value
        if key == 'title.shadow_offset':
            try:
                if isinstance(value, str):
                    # Value is like "5,5", convert to list of numbers
                    offset_parts = [p.strip() for p in value.split(',')]
                    final_value = [float(p) for p in offset_parts]
            except (ValueError, TypeError):
                pass  # If parsing fails, it will use the original value
        elif value.isdigit():
            final_value = int(value)
        elif value.lower() in ['true', 'false']:
            final_value = value.lower() == 'true'
        
        d[parts[-1]] = final_value
            
    config = deep_update(config, form_config)
    
    make_font_paths_absolute(config, PROJECT_ROOT)
    
    title_text = form_data.get('main_title_text', 'Default Text').splitlines()[0]
    
    image = generate_image(config, title_text)
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"generated_{timestamp}.png"
    output_path = os.path.join(GENERATED_DIR, filename)
    image.save(output_path)
    
    image_url = f'/static/generated_images/{filename}'
    return jsonify({'image_url': image_url})


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5001, debug=True)
